package com.dynamic.mybatis.core.generator.method;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.sql.SqlScriptUtils;
import com.dynamic.mybatis.core.generator.MapperMethod;
import com.dynamic.mybatis.core.generator.InjectorMethod;
import com.dynamic.mybatis.core.generator.InjectorHelper;
import com.dynamic.mybatis.core.generator.helper.LogicDeleteHelper;
import com.dynamic.mybatis.core.generator.helper.UpdateInjectorHelper;
import com.dynamic.mybatis.core.metadata.*;
import org.apache.ibatis.builder.MapperBuilderAssistant;
import org.apache.ibatis.executor.keygen.NoKeyGenerator;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.mapping.SqlSource;
import org.apache.ibatis.scripting.LanguageDriver;
import org.apache.ibatis.session.Configuration;

import java.util.List;
import java.util.Map;
import java.util.Optional;

import static java.util.stream.Collectors.joining;
import static java.util.stream.Collectors.toList;

/**
 * @Description
 * @Author xs
 * @Date 2023/4/14 10:13
 */
public class DeleteById extends InjectorMethod {


    public DeleteById() {
        super(MapperMethod.StandardMapperMethod.deleteById);
    }

    @Override
    public String builderScriptSql(String namespace, MappedStatementTable table, MapperBuilderAssistant assistant) {
        Optional<MappedStatementMetaField> LogicDeleteField = InjectorHelper.getLogicDelete(table);
        Optional<MappedStatementMetaField> optionalKeyField = InjectorHelper.getFirstKeyField(table);
        String keyColumn = optionalKeyField.isPresent() ? optionalKeyField.get().getColumn() : null;
        String keyField = optionalKeyField.isPresent() ? optionalKeyField.get().getField() : null;
        String sql;
        if (LogicDeleteField.isPresent()) {
            List<MappedStatementField> fieldInfos = table.getFields().stream()
                    .filter(f -> !f.isLogicDelete())
                    .collect(toList());
            if (CollectionUtils.isNotEmpty(fieldInfos)) {
                String sqlSet = "SET " + SqlScriptUtils.convertIf(fieldInfos.stream()
                        .map(i -> UpdateInjectorHelper.getSqlSet(i, EMPTY)).collect(joining(EMPTY)), "!@org.apache.ibatis.type.SimpleTypeRegistry@isSimpleType(_parameter.getClass())", true)
                        + LogicDeleteHelper.getLogicDeleteSql(table, false, false);
                sql = String.format(getSqlTemplate(), table.getTableName(), sqlSet, keyColumn,
                        keyField, LogicDeleteHelper.getLogicDeleteSql(table, true, true));
            } else {
                sql = String.format(getSqlTemplate(), table.getTableName(), LogicDeleteHelper.sqlLogicSet(table),
                        keyColumn, keyField,
                        LogicDeleteHelper.getLogicDeleteSql(table, true, true));
            }
        } else {
            sql = String.format(getSqlTemplate(), table.getTableName(), keyColumn,
                    keyField);
        }
        return sql;
    }

    @Override
    public DynamicMappedStatement injectMappedStatement(String namespace, MappedStatementTable table, MapperBuilderAssistant assistant) {


        LanguageDriver languageDriver = assistant.getConfiguration().getDefaultScriptingLanguageInstance();
        Configuration configuration = assistant.getConfiguration();
        Optional<MappedStatementMetaField> LogicDeleteField = InjectorHelper.getLogicDelete(table);

        Optional<MappedStatementMetaField> optionalKeyField = InjectorHelper.getFirstKeyField(table);
        String keyColumn = optionalKeyField.isPresent() ? optionalKeyField.get().getColumn() : null;
        String keyField = optionalKeyField.isPresent() ? optionalKeyField.get().getField() : null;

        MappedStatement ms;

        String sql = builderScriptSql(namespace, table, assistant);

        if (LogicDeleteField.isPresent()) {

            SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, Object.class);

            ms = super.addMappedStatement(assistant, table, namespace, sqlSource, SqlCommandType.UPDATE, Map.class, null, Integer.class, NoKeyGenerator.INSTANCE, null, null);

        } else {
            sql = String.format(getSqlTemplate(), table.getTableName(), keyColumn,
                    keyField);
            SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, Map.class);

            ms = super.addMappedStatement(assistant, table, namespace, sqlSource, SqlCommandType.DELETE, Map.class, null, Integer.class, NoKeyGenerator.INSTANCE, null, null);
        }

        return builderDynamicMappedStatement(namespace, table, ms, sql);
    }
}